Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / frontend / NomadPageRenderer.security.test.js

Displaying Raw • Download


tests/frontend/NomadPageRenderer.security.test.js v4.6.0-rc.1 (dc200d15) Text, 9.46 KB

Tff7b72import Tb4b4b4{ Te6edf3describeTb4b4b4, Te6edf3expectTb4b4b4, Te6edf3it Tb4b4b4} Tff7b72from Ta5d6ff"vitest"Tb4b4b4;
Tff7b72import Tb4b4b4{
Te6edf3isolateNomadLinksInHtmlTb4b4b4,
Te6edf3renderNomadHtmlPageTb4b4b4,
Te6edf3renderNomadMarkdownTb4b4b4,
Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4,
Te6edf3sanitizeNomadHtmlFragmentTb4b4b4,
Te6edf3stripExternalFromCssTb4b4b4,
Tb4b4b4} Tff7b72from Ta5d6ff"../../meshchatx/src/frontend/js/NomadPageRenderer"Tb4b4b4;

Tff7b72function Te6edf3assertNoDangerousHtmlPatternsTb4b4b4(Te6edf3htmlTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3lower Tff7b72= Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"<script"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"<iframe"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"javascript:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"vbscript:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"<object"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3lowerTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"<embed"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3describeTb4b4b4(Ta5d6ff"NomadPageRenderer stripExternalFromCss"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3itTb4b4b4(Ta5d6ff"removes @import rules"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3s Tff7b72= Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ff@import url("http://evil.com/a.css"); p { color: red }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"@import"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"evil.com"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/color:\s*red/iTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"blocks url() pointing at http, https, or protocol-relative"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3expectTb4b4b4(Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffa { background: url(http://x/y) }Ta5d6ff`Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"url(blocked:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffa { background: url(https://x/y) }Ta5d6ff`Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"url(blocked:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffa { background: url(//x/y) }Ta5d6ff`Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"url(blocked:"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"allows local-looking and relative css without network url()"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3s Tff7b72= Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffp { color: #333; border: 1px solid currentColor }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"#333"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"currentColor"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"neutralises expression() and IE-style javascript in css"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3expectTb4b4b4(Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffx{width:expression(alert(1))}Ta5d6ff`Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"blocked("Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3stripExternalFromCssTb4b4b4(Ta5d6ff`Ta5d6ffx{foo:javascript:alert(1)}Ta5d6ff`Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"blocked:"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"fuzzing: stripExternalFromCss never throws"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff300Tb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72const Te6edf3len Tff7b72= Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff2000Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3j Tff7b72= T79c0ff0Tb4b4b4; Te6edf3j Tff7b72< Te6edf3lenTb4b4b4; Te6edf3jTff7b72++Tb4b4b4) Tb4b4b4{
Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff65536Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3expectTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3stripExternalFromCssTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toThrowTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Tff7b72typeof Te6edf3stripExternalFromCssTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"string"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3describeTb4b4b4(Ta5d6ff"NomadPageRenderer rewriteCssBodyHtmlSelectors"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3itTb4b4b4(Ta5d6ff"rewrites body and html block openers to nomad-html-root"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Ta5d6ff`Ta5d6ffbody { color: red } html { margin: 0 }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff".nomad-html-root"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/\bbody\s*\{/Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/\bhtml\s*\{/Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"rewrites html, body in selector lists"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Ta5d6ff`Ta5d6ffhtml, body, p { margin: 0 }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff".nomad-html-root"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"rewrites html body descendant selector"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Ta5d6ff`Ta5d6ffhtml body p { margin: 0 }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff".nomad-html-root"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"applies stripExternalFromCss inside rewrite"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Ta5d6ff`Ta5d6ffbody { background: url(https://cdn.example/bg.png) }Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"url(blocked:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/url\s*\(\s*["']?https?:\/\//iTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"fuzzing: rewriteCssBodyHtmlSelectors never throws"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff200Tb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72const Te6edf3len Tff7b72= Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff1500Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3j Tff7b72= T79c0ff0Tb4b4b4; Te6edf3j Tff7b72< Te6edf3lenTb4b4b4; Te6edf3jTff7b72++Tb4b4b4) Tb4b4b4{
Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff65536Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3expectTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toThrowTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Tff7b72typeof Te6edf3rewriteCssBodyHtmlSelectorsTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTb4b4b4(Ta5d6ff"string"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3describeTb4b4b4(Ta5d6ff"NomadPageRenderer HTML document sanitization"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3itTb4b4b4(Ta5d6ff"strips inline event handlers"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(
Ta5d6ff'<body><p onclick="alert(1)" onmouseover="evil()">x</p><img onerror="bad()" src="x"></body>'
Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"onclick"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"onmouseover"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"onerror"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"removes javascript and data-exfil hrefs from anchors"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(
Ta5d6ff'<body><a href="javascript:alert(1)">a</a><a href="data:text/html,<script>x</script>">b</a><a href="https://evil.com">c</a></body>'
Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"javascript:"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"evil.com"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"strips external img src except safe data:image"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(
Ta5d6ff'<body><img src="https://evil.com/i.png"><img src="data:image/png;base64,iVBORw0KGgo="></body>'
Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"evil.com"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"data:image/png"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"sanitises style text with network url in document"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(Ta5d6ff"<body><style>p { background: url(http://x/y) }</style><p>ok</p></body>"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"http://x"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"ok"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"handles nested style in body and head-less fragment"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(Ta5d6ff"<p>x</p><style>body{color:blue}</style>"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"nomad-html-root"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff".nomad-html-root"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"adversarial templates do not throw and omit script-like vectors"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3templates Tff7b72= Tb4b4b4[
Ta5d6ff"<svg onload=alert(1)></svg>"Tb4b4b4,
Ta5d6ff'<math><mi//xlink:href="javascript:alert(1)">'Tb4b4b4,
Ta5d6ff"<body><style>@import 'http://a.com/b.css';</style></body>"Tb4b4b4,
Ta5d6ff"<template><script>alert(1)</script></template>"Tb4b4b4,
Ta5d6ff"<marquee onstart=alert(1)>x</marquee>"Tb4b4b4,
Tffa657StringTb4b4b4.Te6edf3rawTa5d6ff`Ta5d6ff<body><a href="jav&#x09;ascript:alert(1)">x</a></body>Ta5d6ff`Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Te6edf3t Tff7b72of Te6edf3templatesTb4b4b4) Tb4b4b4{
Te6edf3expectTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3renderNomadHtmlPageTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toThrowTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3assertNoDangerousHtmlPatternsTb4b4b4(Te6edf3renderNomadHtmlPageTb4b4b4(Te6edf3tTb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"fuzzing: renderNomadHtmlPage high-volume random and mixed payloads"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3snippets Tff7b72= Tb4b4b4[
Ta5d6ff"<script>x</script>"Tb4b4b4,
Ta5d6ff"<style>body{background:url(https://a.b/c)}</style>"Tb4b4b4,
Ta5d6ff"<iframe src=x></iframe>"Tb4b4b4,
Ta5d6ff"<a href=http://x>y</a>"Tb4b4b4,
Ta5d6ff"<svg><script>.</script></svg>"Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff400Tb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Te6edf3snippetsTb4b4b4[Te6edf3i Tff7b72% Te6edf3snippetsTb4b4b4.Te6edf3lengthTb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3extra Tff7b72= Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff1200Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3j Tff7b72= T79c0ff0Tb4b4b4; Te6edf3j Tff7b72< Te6edf3extraTb4b4b4; Te6edf3jTff7b72++Tb4b4b4) Tb4b4b4{
Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff65536Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72let Te6edf3outTb4b4b4;
Te6edf3expectTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3out Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toThrowTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3assertNoDangerousHtmlPatternsTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3describeTb4b4b4(Ta5d6ff"NomadPageRenderer in-renderer link isolation"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3hash Tff7b72= Ta5d6ff"a"Tb4b4b4.Te6edf3repeatTb4b4b4(T79c0ff32Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"isolateNomadLinksInHtml rewrites /page links to data-nomadnet-url and href #"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3isolateNomadLinksInHtmlTb4b4b4(Ta5d6ff'<p><a href="/page/x.mu">t</a></p>'Tb4b4b4, Te6edf3hashTb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff`Ta5d6ffdata-nomadnet-url="Tffd700${Te6edf3hashTffd700}Ta5d6ff:/page/x.mu"Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff'href="#"'Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff'href="/page/'Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"renderNomadHtmlPage with destinationHash isolates relative links"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadHtmlPageTb4b4b4(Ta5d6ff'<body><a href="/page/a.html">x</a></body>'Tb4b4b4, Tb4b4b4{ Te6edf3destinationHashTff7b72: Te6edf3hash Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff`Ta5d6ffdata-nomadnet-url="Tffd700${Te6edf3hashTffd700}Ta5d6ff:/page/a.html"Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/href="\/page\//Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"renderNomadMarkdown with destinationHash isolates relative links"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadMarkdownTb4b4b4(Ta5d6ff"[l](/page/b.md)"Tb4b4b4, Tb4b4b4{ Te6edf3destinationHashTff7b72: Te6edf3hash Tb4b4b4}Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff`Ta5d6ffdata-nomadnet-url="Tffd700${Te6edf3hashTffd700}Ta5d6ff:/page/b.md"Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toMatchTb4b4b4(Ta5d6ff/href="\/page\//Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3describeTb4b4b4(Ta5d6ff"NomadPageRenderer fragment and markdown sanitization"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3itTb4b4b4(Ta5d6ff"sanitizeNomadHtmlFragment removes script and keeps safe markup"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3out Tff7b72= Te6edf3sanitizeNomadHtmlFragmentTb4b4b4(Ta5d6ff"<div>ok</div><script>bad</script>"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4.Te6edf3toLowerCaseTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"<script"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3outTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"ok"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"markdown pipeline does not emit executable URLs"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3md Tff7b72= Ta5d6ff"[l](javascript:void(0))\n\n[ext](https://bad.example)\n\n`code`"Tb4b4b4;
Tff7b72const Te6edf3html Tff7b72= Te6edf3renderNomadMarkdownTb4b4b4(Te6edf3mdTb4b4b4)Tb4b4b4;
Te6edf3assertNoDangerousHtmlPatternsTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3htmlTb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"bad.example"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3itTb4b4b4(Ta5d6ff"fuzzing: sanitizeNomadHtmlFragment and renderNomadMarkdown combined stress"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3i Tff7b72< T79c0ff250Tb4b4b4; Te6edf3iTff7b72++Tb4b4b4) Tb4b4b4{
Tff7b72let Te6edf3s Tff7b72= Ta5d6ff""Tb4b4b4;
Tff7b72const Te6edf3len Tff7b72= Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff600Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72let Te6edf3j Tff7b72= T79c0ff0Tb4b4b4; Te6edf3j Tff7b72< Te6edf3lenTb4b4b4; Te6edf3jTff7b72++Tb4b4b4) Tb4b4b4{
Te6edf3s Tff7b72+= Tffa657StringTb4b4b4.Te6edf3fromCharCodeTb4b4b4(Tffa657MathTb4b4b4.Te6edf3floorTb4b4b4(Tffa657MathTb4b4b4.Te6edf3randomTb4b4b4(Tb4b4b4) Tff7b72* T79c0ff65536Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3expectTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3sanitizeNomadHtmlFragmentTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3notTb4b4b4.Te6edf3toThrowTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3mdHtml Tff7b72= Te6edf3renderNomadMarkdownTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4;
Te6edf3assertNoDangerousHtmlPatternsTb4b4b4(Te6edf3mdHtmlTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4, T79c0ff30Te6edf3_000Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────